#include "GameRules.h"
#include "StringManager.h"

GameRules * GameRules::instance = NULL;

GameRules::GameRules(void)
{
}

GameRules * GameRules::Instance()
{
	if ( instance == 0 )
		instance = new GameRules();

	return instance;
}

GameRules::~GameRules(void)
{
}

void GameRules::Initialise(GameTypes gameType, int level, double levelNumber)
{
	SetGameType(gameType);
	SetLevel(level);
}

Board * GameRules::GenerateBoard()
{
	srand(5);

	Board * board = new Board();

	for(int x = 0; x < BOARD_SIZE_X; x++)
		for (int y = 0; y < BOARD_SIZE_Y; y++)
		{

			double cellNumber = 0;

			switch(gameType)
			{
			case MULTIPLES:	
				if( (rand() % 2) == 0 ) //generate a invalid number 1 out of 3 times (0,1,2)
					cellNumber = ( rand() % (level+2) );
				else
					cellNumber = ((rand() % level+2) * levelNumber );
				break;
			case FACTORS:
				cellNumber = (rand() % (int)levelNumber);
				break;
			case PRIMES:
				cellNumber = (rand() % 20);
				break;

			case EQUALITY:
				cellNumber = (rand() % 20);
				break;
			}

			BoardCell * cell = new BoardCell( StringManager::ToStr(cellNumber) );
			cell->SetScale(0.5,0.5,0.5);

			//TODO: calculate this based on the board size
			//TODO: also need to take into account of the length of the text
			cell->SetPosition(-2.25+x, 0.6, 1.5-y); 
			board->boardCells[x][y] = cell;
			board->AddChild((SceneNode*)cell); //add cell to scene graph so it get rendered

		}

	return board;

}

bool GameRules::IsEdible(BoardCell * boardCell)
{
	switch(gameType)
	{
	case MULTIPLES:		
		if ( ((int)boardCell->GetCellNumber() % (int)levelNumber) == 0 )
			return true;

		break;
	case FACTORS:
		if ( ((int)levelNumber % (int)boardCell->GetCellNumber()) == 0 )
			return true;
		break;
	case PRIMES:
		
		break;

	case EQUALITY:
		
		break;
	}

	return false;
}

bool GameRules::BoardComplete(Board * board)
{
	for(int x = 0; x < BOARD_SIZE_X; x++)
		for (int y = 0; y < BOARD_SIZE_Y; y++)
		{
			if( IsEdible(board->boardCells[x][y]) && !board->boardCells[x][y]->IsEaten() )
				return false; //theres still cells to be eaten
		}

	return true;
}

void GameRules::SetGameType(GameTypes gameType)
{
	this->gameType = gameType;
}

GameTypes GameRules::GetGameType()
{
	return this->gameType;
}

void GameRules::SetLevel(int level)
{
	//assert( level > 0 );

	this->level = level;

		//set the levelNumber based on the game type and the current level
	srand(GetTickCount());

	switch(gameType)
	{
	case MULTIPLES:				
		levelNumber = rand() % 5 + level * (rand() % 5); //TODO: maybe a look up table of some sorts
		break;
	case FACTORS:
		levelNumber = (rand() % (int)levelNumber);
		break;
	case PRIMES:
		levelNumber = (rand() % 20); //TODO
		break;

	case EQUALITY:
		levelNumber = (rand() % 20); //TODO
		break;
	}

	SetLevelNumber(levelNumber);
}

int GameRules::GetLevel()
{
	return this->level;
}

void GameRules::SetLevelNumber(double levelNumber)
{
	this->levelNumber = levelNumber;
}

double GameRules::GetLevelNumber()
{
	return this->levelNumber;
}

std::wstring GameRules::GetLevelString()
{
	switch(gameType)
	{
	case MULTIPLES:		
		return L"Multiples of " + StringManager::ToStr(levelNumber);
	case FACTORS:
		return L"Factors of " + StringManager::ToStr(levelNumber);
	case PRIMES:
		return L"Prime Numbers";
	case EQUALITY:
		return L"Equals " + StringManager::ToStr(levelNumber);
		break;
	}
}